﻿using System;
using System.Collections.Generic;
using System.Threading;

namespace Pay.Service.Cache {
    public class BlockQueue<T> {
        private Queue<T> _inner_queue = null;

        private ManualResetEvent _dequeue_wait = null;

        public int Count {
            get { return _inner_queue.Count; }
        }

        public BlockQueue(int capacity = -1) {
            _inner_queue = capacity == -1 ? new Queue<T>() : new Queue<T>(capacity);
            _dequeue_wait = new ManualResetEvent(false);
        }

        public void EnQueue(T item) {
            if (_IsShutdown == true) throw new InvalidOperationException("服务未开启.[EnQueue]");

            lock (_inner_queue) {
                _inner_queue.Enqueue(item);
                _dequeue_wait.Set();
            }
        }

        public T DeQueue(int waitTime) {
            bool _queueEmpty = false;
            T item = default(T);
            while (true) {
                lock (_inner_queue) {
                    if (_inner_queue.Count > 0) {
                        item = _inner_queue.Dequeue();
                        _dequeue_wait.Reset();
                        //break;
                    } else {
                        if (_IsShutdown == true) {
                            throw new InvalidOperationException("服务未开启[DeQueue].");
                        } else {
                            _queueEmpty = true;
                        }
                    }
                }
                if (item != null) {
                    return item;
                }
                if (_queueEmpty) {
                    _dequeue_wait.WaitOne(waitTime);
                }
            }

        }

        private bool _IsShutdown = false;

        public void Shutdown() {
            _IsShutdown = true;
            _dequeue_wait.Set();
        }

        public void Clear() {
            _inner_queue.Clear();
        }
    }
}
